/*
 * @(#)CamCache.java
 * 
 * Create Version: 1.0.0
 * Author: James Liu
 * Create Date: 2009-12-09
 * 
 * Copyright (c) 2009 ASPire Information Technologies Ltd. All Right Reserved.
 */
package com.aspire.boc.mms.wmf.cam;


import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;

import com.aspire.boc.mms.wmf.util.Configuration;


/**
 * 这个类表示CAM本地缓存，它是独子模式的。
 * 
 * @version 1.0.0   2009-12-09
 * @author  James Liu
 */
public class CamCache {
    
    private static Log log = LogFactory.getLog(CamCache.class);
    private static CamCache instance = new CamCache();
    
    private volatile Data cache = new Data();
    
    
    private CamCache() {
    	 log.info(">>>>>>>>>>>权限缓存加载  .........");
        this.load();
        log.info(">>>>>>>>>>> 权限缓存加载  完成.........");
    }
    
    public static CamCache getInstance() {
        
        return instance;
    }
    
    
    /**
     * 全局系统组
     * @Title: getGroups 
     * @Description: TODO(这里用一句话描述这个方法的作用) 
     * @return
     */
    public Set<Group>  getGroups() {
        return this.cache.groups;
    }
    
    /**
     * 全局系统用户
     * @Title: getGroups 
     * @Description: TODO(这里用一句话描述这个方法的作用) 
     * @return
     */
    public Set<User>  getUsers() {
        return this.cache.users;
    }
    
    /**
     * 全局系统角色
     * @Title: getGroups 
     * @Description: TODO(这里用一句话描述这个方法的作用) 
     * @return
     */
    public Set<Role>  getRoles() {
        return this.cache.roles;
    }
    
    
	synchronized void load() {
        
        String xmlRpcServerUrl = Configuration.getConfiguration("system.permission.url");
        String system_def = Configuration.getConfiguration("system.permission.system_def");
        
        try {
            Vector<Object> params = new Vector<Object>();
            params.add(system_def);
            
            XmlRpcClient client = new XmlRpcClient(xmlRpcServerUrl);
            Vector<?> results = (Vector<?>) client.execute("UserService.getWholeInfo", params);
            Data data = new Data();
            if(results == null) {
                this.cache = data;
                return;
            }
            // Groups
            Map<Integer, Group> groups = new LinkedHashMap<Integer, Group>();
            Hashtable<?, ?> allGroups = (Hashtable<?, ?>) results.get(0); //results[0];
            Iterator<?> groupIdIter = allGroups.keySet().iterator();
            while (groupIdIter.hasNext()) {
                String groupId = (String) groupIdIter.next();
                Map<?, ?> groupPO = (Map<?, ?>) allGroups.get(groupId);
                Group group = new Group();
                group.setId((Integer) groupPO.get("group_id"));
                group.setName((String) groupPO.get("group_name"));
                group.setAdministrator((String) groupPO.get("user_name"));
                group.setLevel((Integer) groupPO.get("level_id"));
                group.setParentId((Integer) groupPO.get("parent_group_id"));
                group.setSystemDef((String) groupPO.get("system_def"));
                group.setDesc((String) groupPO.get("group_descr"));
                groups.put(group.getId(), group);
                data.getGroups().add(group);
            }
            Iterator<Integer> groupIdIntegerIter = groups.keySet().iterator();
            while (groupIdIntegerIter.hasNext()) {
                Integer groupId = groupIdIntegerIter.next();
                Group group = groups.get(groupId);
                Group parent = groups.get(group.getParentId());
                if (parent != null) {
                    parent.getChildren().add(group);
                    group.setParent(parent);
                }
            }
            
            // Roles
            Map<Integer, Role> roles = new LinkedHashMap<Integer, Role>();
            Hashtable<?, ?> allRoles = (Hashtable<?, ?>) results.get(1); //results[1]
            Iterator<?> roleIdIter = allRoles.keySet().iterator();
            while (roleIdIter.hasNext()) {
                String roleId = (String) roleIdIter.next();
                Map<?, ?> rolePO = (Map<?, ?>) allRoles.get(roleId);
                Role role = new Role();
                role.setId((Integer) rolePO.get("role_id"));
                role.setName((String) rolePO.get("role_name"));
                role.setDesc((String) rolePO.get("role_descr"));
                role.setSystemDef((String) rolePO.get("system_def"));
                roles.put(role.getId(), role);
                data.getRoles().add(role);
            }
            
            // Users
            Map<Integer, User> users = new LinkedHashMap<Integer, User>();
            Hashtable<?, ?> allUsers = (Hashtable<?, ?>) results.get(2); //results[2]
            Iterator<?> userIdIter = allUsers.keySet().iterator();
            while (userIdIter.hasNext()) {
                String userId = (String) userIdIter.next();
                Map<?, ?> userPO = (Map<?, ?>) allUsers.get(userId);
                User user = new User();
                user.setId((Integer) userPO.get("user_id"));
                user.setName((String) userPO.get("user_name"));
                user.setRealName((String) userPO.get("real_name"));
                user.setSex(Integer.parseInt(((String) userPO.get("sex"))));
                //user.setBirthDate((Date) userPO.get("birth_date"));
                user.setState4Bool((Boolean) userPO.get("state4Bool"));
                user.setMobile((String) userPO.get("mobile"));
                user.setEmail((String) userPO.get("email"));
                user.setEnrollDate((Date) userPO.get("enroll_date"));
                user.setLastUpdateDate((Date) userPO.get("last_upd_date"));
                users.put(user.getId(), user);
                data.getUsers().add(user);
            }
            
            // Group and Role
            Vector<?> groupAndRoleObjs = (Vector<?>) results.get(3); //results[3]
            for (Object groupAndRoleObj : groupAndRoleObjs) {
                Map<?, ?> groupAndRole = (Map<?, ?>) groupAndRoleObj;
                Integer roleId = (Integer) groupAndRole.get("role_id");
                Integer groupId = (Integer) groupAndRole.get("group_id");
                Role role = roles.get(roleId);
                Group group = groups.get(groupId);
                if ((role != null) && (group != null)) {
                    role.getGroups().add(group);
                    group.getRoles().add(role);
                }
            }
            
            // Group and User
            Vector<?> groupAndUserObjs = (Vector<?>) results.get(4); //results[4]
            for (Object groupAndUserObj : groupAndUserObjs) {
                Map<?, ?> groupAndUser = (Map<?, ?>) groupAndUserObj;
                Integer userId = (Integer) groupAndUser.get("user_id");
                Integer groupId = (Integer) groupAndUser.get("group_id");
                User user = users.get(userId);
                Group group = groups.get(groupId);
                if ((user != null) && (group != null)) {
                    user.getGroups().add(group);
                    group.getUsers().add(user);
                }
            }
            
            // User, Group and Role
            Vector<?> userGroupRoleObjs = (Vector<?>) results.get(5); //results[5]
            for (Object userGroupRoleObj : userGroupRoleObjs) {
                Map<?, ?> userGroupRole = (Map<?, ?>) userGroupRoleObj;
                Integer userId = (Integer) userGroupRole.get("user_id");
                Integer roleId = (Integer) userGroupRole.get("role_id");
                Integer groupId = (Integer) userGroupRole.get("group_id");
                User user = users.get(userId);
                Role role = roles.get(roleId);
                Group group = groups.get(groupId);
                if ((user != null) && (role != null) && (group != null)) {
                    user.getRoles().add(role);
                    user.getGroups().add(group);
                    role.getUsers().add(user);
                    role.getGroups().add(group);
                    group.getUsers().add(user);
                    group.getRoles().add(role);
                }
            }
            this.cache = data;
        } catch (MalformedURLException e) {
            log.error("CAM xml rpc server url error!", e);
        } catch (XmlRpcException e) {
            log.error("CAM xml rpc service error!", e);
        } catch (IOException e) {
            log.error("CAM xml rpc service error!", e);
        }
    }
    

    static class Data {
        
        private Set<User> users = new LinkedHashSet<User>();
        private Set<Role> roles = new LinkedHashSet<Role>();
        private Set<Group> groups = new LinkedHashSet<Group>();
        
        private Data() {}
        
        public Set<User> getUsers() {
        
            return users;
        }
        
        public void setUsers(Set<User> users) {
        
            this.users = users;
        }
        
        public Set<Role> getRoles() {
        
            return roles;
        }
        
        public void setRoles(Set<Role> roles) {
        
            this.roles = roles;
        }
        
        public Set<Group> getGroups() {
        
            return groups;
        }
        
        public void setGroups(Set<Group> groups) {
        
            this.groups = groups;
        }
    }
}